import { Injectable } from '@nestjs/common';
import * as _ from 'lodash';

/**
 * Lodash 工具函数服务
 * 基于 NestJS 官方示例实现
 * 参考: https://docs.nestjs.cn/fundamentals/dependency-injection
 * 对应 Java: StringUtils, ObjectUtils, ArrayUtils
 */
@Injectable()
export class LodashService {
  /**
   * 获取 lodash 实例
   */
  getLodash(): any {
    return _;
  }

  // ==================== 字符串工具 ====================

  /**
   * 判断字符串是否为空
   */
  isEmpty(value: any): boolean {
    return _.isEmpty(value);
  }

  /**
   * 判断字符串是否不为空
   */
  isNotEmpty(value: any): boolean {
    return !_.isEmpty(value);
  }

  /**
   * 首字母大写
   */
  capitalize(str: string): string {
    return _.capitalize(str);
  }

  /**
   * 驼峰转下划线
   */
  snakeCase(str: string): string {
    return _.snakeCase(str);
  }

  /**
   * 下划线转驼峰
   */
  camelCase(str: string): string {
    return _.camelCase(str);
  }

  /**
   * 转换为大写
   */
  upperCase(str: string): string {
    return _.upperCase(str);
  }

  /**
   * 转换为小写
   */
  lowerCase(str: string): string {
    return _.lowerCase(str);
  }

  /**
   * 转换为标题格式
   */
  startCase(str: string): string {
    return _.startCase(str);
  }

  /**
   * 截取字符串
   */
  truncate(str: string, options?: _.TruncateOptions): string {
    return _.truncate(str, options);
  }

  /**
   * 移除字符串两端空白
   */
  trim(str: string, chars?: string): string {
    return _.trim(str, chars);
  }

  /**
   * 移除字符串左端空白
   */
  trimStart(str: string, chars?: string): string {
    return _.trimStart(str, chars);
  }

  /**
   * 移除字符串右端空白
   */
  trimEnd(str: string, chars?: string): string {
    return _.trimEnd(str, chars);
  }

  /**
   * 重复字符串
   */
  repeat(str: string, n: number): string {
    return _.repeat(str, n);
  }

  /**
   * 生成随机字符串
   */
  randomString(
    length: number = 8,
    chars: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
  ): string {
    return _.sampleSize(chars, length).join('');
  }

  // ==================== 对象工具 ====================

  /**
   * 判断是否为对象
   */
  isObject(value: any): boolean {
    return _.isObject(value);
  }

  /**
   * 判断是否为数组
   */
  isArray(value: any): boolean {
    return _.isArray(value);
  }

  /**
   * 判断是否为函数
   */
  isFunction(value: any): boolean {
    return _.isFunction(value);
  }

  /**
   * 判断是否为数字
   */
  isNumber(value: any): boolean {
    return _.isNumber(value);
  }

  /**
   * 判断是否为字符串
   */
  isString(value: any): boolean {
    return _.isString(value);
  }

  /**
   * 判断是否为布尔值
   */
  isBoolean(value: any): boolean {
    return _.isBoolean(value);
  }

  /**
   * 判断是否为日期
   */
  isDate(value: any): boolean {
    return _.isDate(value);
  }

  /**
   * 判断是否为 null
   */
  isNull(value: any): boolean {
    return _.isNull(value);
  }

  /**
   * 判断是否为 undefined
   */
  isUndefined(value: any): boolean {
    return _.isUndefined(value);
  }

  /**
   * 判断是否为 null 或 undefined
   */
  isNil(value: any): boolean {
    return _.isNil(value);
  }

  /**
   * 深度合并对象
   */
  merge<T extends object>(target: T, ...sources: Partial<T>[]): T {
    return _.merge(target, ...sources);
  }

  /**
   * 从对象中提取指定属性
   */
  pick<T extends object, K extends keyof T>(
    object: T,
    ...paths: K[]
  ): Pick<T, K> {
    return _.pick(object, ...paths);
  }

  /**
   * 从对象中排除指定属性
   */
  omit<T extends object, K extends keyof T>(
    object: T,
    ...paths: K[]
  ): Omit<T, K> {
    return _.omit(object, ...paths);
  }

  /**
   * 获取对象属性值
   */
  get<T = any>(object: any, path: string, defaultValue?: T): T {
    return _.get(object, path, defaultValue);
  }

  /**
   * 设置对象属性值
   */
  set<T = any>(object: any, path: string, value: T): any {
    return _.set(object, path, value);
  }

  /**
   * 判断对象是否有指定属性
   */
  has(object: any, path: string): boolean {
    return _.has(object, path);
  }

  /**
   * 删除对象属性
   */
  unset(object: any, path: string): boolean {
    return _.unset(object, path);
  }

  /**
   * 获取对象的所有键
   */
  keys(object: any): string[] {
    return _.keys(object);
  }

  /**
   * 获取对象的所有值
   */
  values(object: any): any[] {
    return _.values(object);
  }

  /**
   * 获取对象的所有键值对
   */
  entries(object: any): [string, any][] {
    return _.entries(object);
  }

  /**
   * 将键值对数组转换为对象
   */
  fromPairs(pairs: [string, any][]): object {
    return _.fromPairs(pairs);
  }

  /**
   * 将对象转换为键值对数组
   */
  toPairs(object: any): [string, any][] {
    return _.toPairs(object);
  }

  // ==================== 数组工具 ====================

  /**
   * 数组去重
   */
  uniq<T>(array: T[]): T[] {
    return _.uniq(array);
  }

  /**
   * 数组去重（根据指定属性）
   */
  uniqBy<T>(array: T[], iteratee: string | ((item: T) => any)): T[] {
    return _.uniqBy(array, iteratee);
  }

  /**
   * 数组去重（根据指定函数）
   */
  uniqWith<T>(array: T[], comparator: (a: T, b: T) => boolean): T[] {
    return _.uniqWith(array, comparator);
  }

  /**
   * 数组分组
   */
  groupBy<T>(
    array: T[],
    iteratee: string | ((item: T) => any),
  ): Record<string, T[]> {
    return _.groupBy(array, iteratee);
  }

  /**
   * 数组排序
   */
  sortBy<T>(array: T[], ...iteratees: (string | ((item: T) => any))[]): T[] {
    return _.sortBy(array, ...iteratees);
  }

  /**
   * 数组过滤
   */
  filter<T>(array: T[], predicate: (item: T) => boolean): T[] {
    return _.filter(array, predicate);
  }

  /**
   * 数组映射
   */
  map<T, U>(array: T[], iteratee: (item: T, index: number) => U): U[] {
    return _.map(array, iteratee);
  }

  /**
   * 数组查找
   */
  find<T>(array: T[], predicate: (item: T) => boolean): T | undefined {
    return _.find(array, predicate);
  }

  /**
   * 数组查找索引
   */
  findIndex<T>(array: T[], predicate: (item: T) => boolean): number {
    return _.findIndex(array, predicate);
  }

  /**
   * 数组包含
   */
  includes<T>(array: T[], value: T): boolean {
    return _.includes(array, value);
  }

  /**
   * 数组切片
   */
  slice<T>(array: T[], start?: number, end?: number): T[] {
    return _.slice(array, start, end);
  }

  /**
   * 数组分块
   */
  chunk<T>(array: T[], size: number): T[][] {
    return _.chunk(array, size);
  }

  /**
   * 数组扁平化
   */
  flatten<T>(array: T[][]): T[] {
    return _.flatten(array);
  }

  /**
   * 数组深度扁平化
   */
  flattenDeep<T>(array: any[]): T[] {
    return _.flattenDeep(array);
  }

  /**
   * 数组压缩
   */
  compact<T>(array: T[]): T[] {
    return _.compact(array);
  }

  /**
   * 数组连接
   */
  concat<T>(array: T[], ...values: any[]): T[] {
    return _.concat(array, ...values);
  }

  /**
   * 数组差集
   */
  difference<T>(array: T[], ...values: T[][]): T[] {
    return _.difference(array, ...values);
  }

  /**
   * 数组交集
   */
  intersection<T>(...arrays: T[][]): T[] {
    return _.intersection(...arrays);
  }

  /**
   * 数组并集
   */
  union<T>(...arrays: T[][]): T[] {
    return _.union(...arrays);
  }

  /**
   * 数组求和
   */
  sum(array: number[]): number {
    return _.sum(array);
  }

  /**
   * 数组平均值
   */
  mean(array: number[]): number {
    return _.mean(array);
  }

  /**
   * 数组最大值
   */
  max<T>(array: T[]): T | undefined {
    return _.max(array);
  }

  /**
   * 数组最小值
   */
  min<T>(array: T[]): T | undefined {
    return _.min(array);
  }

  /**
   * 数组随机元素
   */
  sample<T>(array: T[]): T | undefined {
    return _.sample(array);
  }

  /**
   * 数组随机元素（多个）
   */
  sampleSize<T>(array: T[], n: number): T[] {
    return _.sampleSize(array, n);
  }

  /**
   * 数组洗牌
   */
  shuffle<T>(array: T[]): T[] {
    return _.shuffle(array);
  }

  /**
   * 数组取前N个
   */
  take<T>(array: T[], n: number): T[] {
    return _.take(array, n);
  }

  /**
   * 数组取后N个
   */
  takeRight<T>(array: T[], n: number): T[] {
    return _.takeRight(array, n);
  }

  /**
   * 数组跳过前N个
   */
  drop<T>(array: T[], n: number): T[] {
    return _.drop(array, n);
  }

  /**
   * 数组跳过后N个
   */
  dropRight<T>(array: T[], n: number): T[] {
    return _.dropRight(array, n);
  }

  // ==================== 函数工具 ====================

  /**
   * 函数防抖
   */
  debounce<T extends (...args: any[]) => any>(
    func: T,
    wait: number,
    options?: _.DebounceSettings,
  ): any {
    return _.debounce(func, wait, options);
  }

  /**
   * 函数节流
   */
  throttle<T extends (...args: any[]) => any>(
    func: T,
    wait: number,
    options?: _.ThrottleSettings,
  ): any {
    return _.throttle(func, wait, options);
  }

  /**
   * 函数柯里化
   */
  curry<T extends (...args: any[]) => any>(func: T): any {
    return _.curry(func);
  }

  /**
   * 函数记忆化
   */
  memoize<T extends (...args: any[]) => any>(
    func: T,
    resolver?: (...args: any[]) => string,
  ): T {
    return _.memoize(func, resolver);
  }

  // ==================== 数字工具 ====================

  /**
   * 数字范围
   */
  range(start: number, end?: number, step?: number): number[] {
    return _.range(start, end, step);
  }

  /**
   * 数字随机
   */
  random(lower: number, upper?: number, floating?: boolean): number {
    if (upper === undefined) {
      return _.random(lower);
    }
    return _.random(lower, upper, floating);
  }

  /**
   * 数字四舍五入
   */
  round(number: number, precision?: number): number {
    return _.round(number, precision);
  }

  /**
   * 数字向上取整
   */
  ceil(number: number, precision?: number): number {
    return _.ceil(number, precision);
  }

  /**
   * 数字向下取整
   */
  floor(number: number, precision?: number): number {
    return _.floor(number, precision);
  }

  /**
   * 数字截断
   */
  trunc(number: number, precision?: number): number {
    return (
      Math.trunc(number * Math.pow(10, precision || 0)) /
      Math.pow(10, precision || 0)
    );
  }

  // ==================== 集合工具 ====================

  /**
   * 集合大小
   */
  size(collection: any): number {
    return _.size(collection);
  }

  /**
   * 集合遍历
   */
  forEach<T>(
    collection: T[],
    iteratee: (value: T, index: number, collection: T[]) => void,
  ): T[] {
    return _.forEach(collection, iteratee);
  }

  /**
   * 集合映射
   */
  mapValues<T, U>(
    object: Record<string, T>,
    iteratee: (value: T, key: string) => U,
  ): Record<string, U> {
    return _.mapValues(object, iteratee);
  }

  /**
   * 集合键映射
   */
  mapKeys<T>(
    object: Record<string, T>,
    iteratee: (value: T, key: string) => string,
  ): Record<string, T> {
    return _.mapKeys(object, iteratee);
  }

  /**
   * 集合键过滤
   */
  pickBy<T>(
    object: Record<string, T>,
    predicate: (value: T, key: string) => boolean,
  ): Record<string, T> {
    return _.pickBy(object, predicate);
  }

  /**
   * 集合键排除
   */
  omitBy<T>(
    object: Record<string, T>,
    predicate: (value: T, key: string) => boolean,
  ): Record<string, T> {
    return _.omitBy(object, predicate);
  }

  /**
   * 集合键反转
   */
  invert(object: Record<string, any>): Record<string, string> {
    return _.invert(object);
  }

  /**
   * 集合键反转（保持值）
   */
  invertBy<T>(
    object: Record<string, T>,
    iteratee?: (value: T) => string,
  ): Record<string, string[]> {
    return _.invertBy(object, iteratee);
  }
}
